home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
X11
/
xarchie-2.0.9
/
db.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-06-18
|
9KB
|
432 lines
/*
* db.c : Database routines for xarchie
*
* George Ferguson, ferguson@cs.rochester.edu, 2 Nov 1991.
* Version 2.0: 23 Apr 1993.
*/
#include <stdio.h>
#include "db.h"
#include "weight.h"
#include "stringdefs.h"
#include "debug.h"
#ifdef XARCHIE
# include <X11/Intrinsic.h>
#else /*!XARCHIE*/
# include "xtypes.h"
#endif
/*
* Functions defined here:
*/
DbEntry *newEntry();
void clearEntries();
DbEntry *addEntry();
DbEntry *lastEntry();
DbEntry *findEntryFromString();
DbEntry *findEntryFromIndex();
int findIndexFromEntry();
void setEntryData(), freeEntryData();
void sortEntriesRecursively(), sortEntries();
int cmpEntryNames(), cmpEntryDates(), cmpEntryWeights();
static void clearEntriesInternal();
static char *entryDate(),*hostDate(),*locationDate();
/* - - - - - - - - */
DbEntry *
newEntry()
{
DbEntry *new;
new = XtNew(DbEntry);
new->name = NULL;
new->type = DB_NOTYPE;
new->size = -1;
new->modes = "";
new->date = "";
new->gt_date = "";
new->vlink = NULL;
new->selected = -1;
new->entries = NULL;
new->next = new->prev = new->parent = NULL;
return(new);
}
void
clearEntries(dbp)
DbEntry *dbp;
{
if (dbp == NULL) {
fprintf(stderr,"DB Error: Attempt to clear NULL list\n");
return;
} else {
clearEntriesInternal(dbp->entries);
dbp->entries = NULL;
}
}
static void
clearEntriesInternal(dbp)
DbEntry *dbp;
{
DbEntry *t;
while (dbp != NULL) {
clearEntriesInternal(dbp->entries);
freeEntryData(dbp);
t = dbp;
dbp = dbp->next;
XtFree((char *)t);
}
}
/* - - - - - - - - */
DbEntry *
addEntry(parent,before)
DbEntry *parent;
DbEntry *before;
{
DbEntry *new,*last;
DEBUG2("adding entry to 0x%x before 0x%x\n",parent,before);
if (parent == NULL) {
fprintf(stderr,"DB error: attempt to add entry to NULL list\n");
return(NULL);
} else if (parent->entries == NULL) {
/* No items already in list */
DEBUG0(" inserting as new list\n");
new = XtNew(DbEntry);
DEBUG1(" new entry is 0x%x\n",new);
parent->entries = new;
new->prev = NULL;
new->next = NULL;
} else if (before == NULL) {
/* Insert at end of list */
DEBUG0(" inserting at end of list\n");
last = lastEntry(parent);
new = XtNew(DbEntry);
DEBUG1(" new entry is 0x%x\n",new);
last->next = new;
new->prev = last;
new->next = NULL;
} else if (before->prev == NULL) {
/* Insert at head of list */
DEBUG0(" inserting at head of list\n");
new = XtNew(DbEntry);
DEBUG1(" new entry is 0x%x\n",new);
parent->entries = new;
new->prev = NULL;
new->next = before;
before->prev = new;
} else {
/* Insert somewhere in the middle of list */
DEBUG0(" inserting in middle of list\n");
new = XtNew(DbEntry);
DEBUG1(" new entry is 0x%x\n",new);
before->prev->next = new;
new->prev = before->prev;
new->next = before;
before->prev = new;
}
new->parent = parent;
new->entries = NULL;
new->name = NULL;
new->type = DB_NOTYPE;
new->size = -1;
new->modes = "";
new->date = "";
new->gt_date = "";
new->vlink = NULL;
DEBUG0(" done adding new entry\n");
return(new);
}
DbEntry *
lastEntry(parent)
DbEntry *parent;
{
DbEntry *dbp;
DEBUG1("finding last entry in entries for 0x%x\n",parent);
if (parent == NULL) {
fprintf(stderr,"DB error: attempt to find last entry of NULL list\n");
return(NULL);
} else if (parent->entries == NULL) {
DEBUG1("no entries for 0x%x, returning NULL\n",parent);
return(NULL);
} else {
for (dbp=parent->entries; dbp->next != NULL; dbp=dbp->next)
/* EMPTY */ ;
DEBUG2("last entry for 0x%x is 0x%x\n",parent,dbp);
return(dbp);
}
}
DbEntry *
findEntryFromString(parent,string)
DbEntry *parent;
char *string;
{
DbEntry *dbp;
DEBUG2("finding entry \"%s\" in entries for 0x%x\n",string,parent);
if (parent == NULL) {
fprintf(stderr,"DB error: attempt to find \"%s\" in NULL list",string);
return(NULL);
} else {
for (dbp=parent->entries; dbp != NULL &&
strcmp(dbp->name,string) != 0; dbp=dbp->next)
/* EMPTY */ ;
DEBUG1(" find returning 0x%x\n",dbp);
return(dbp);
}
}
DbEntry *
findEntryFromIndex(parent,index)
DbEntry *parent;
int index;
{
DbEntry *dbp;
DEBUG2("finding entry with index %d in entries for 0x%x\n",index,parent);
if (parent == NULL) {
fprintf(stderr,"DB error: attempt to find index %d in NULL list",index);
return(NULL);
} else {
for (dbp=parent->entries; dbp != NULL && index--; dbp=dbp->next)
/* EMPTY */ ;
DEBUG1(" find returning 0x%x\n",dbp);
return(dbp);
}
}
int
findIndexFromEntry(parent,entry)
DbEntry *parent,*entry;
{
DbEntry *dbp;
int index;
DEBUG2("finding index for entry 0x%x in entries for 0x%x\n",entry,parent);
index = 0;
if (parent == NULL) {
fprintf(stderr,"DB error: attempt to find entry 0x%x in NULL list",entry);
return(0);
} else {
for (dbp=parent->entries; dbp != NULL; dbp=dbp->next) {
if (strcmp(entry->name,dbp->name) == 0) {
DEBUG1(" return index %d\n",index);
return(index);
}
index += 1;
}
}
return(-1);
}
/* - - - - - - - - */
/*
* Allocate and set the data for the given DbEntry.
*/
void
setEntryData(dbp,name,type,size,modes,date,gt_date,vlink)
DbEntry *dbp;
char *name;
int type;
int size;
char *modes,*date,*gt_date;
VLINK vlink;
{
XtFree(dbp->name);
dbp->name = XtNewString(name);
dbp->type = type;
dbp->size = size;
dbp->modes = XtNewString(modes);
dbp->date = XtNewString(date);
dbp->gt_date = XtNewString(gt_date);
dbp->vlink = vlink;
DEBUG2("set data for entry 0x%x, name=\"%s\"\n",dbp,dbp->name);
}
/*
* Free up anything associated with the given DbEntry.
*/
void
freeEntryData(dbp)
DbEntry *dbp;
{
XtFree((char *)(dbp->name));
if (dbp->vlink)
vlfree(dbp->vlink);
}
/* - - - - - - - - */
/*
* Sorts entries of parent and then calls itself on each of them.
*/
void
sortEntriesRecursively(parent,cmp_proc)
DbEntry *parent;
int (*cmp_proc)();
{
DbEntry *dbp;
if (parent == NULL || cmp_proc == NULL)
return;
DEBUG1(" sorting entries recursively for 0x%x\n",parent);
sortEntries(parent,cmp_proc);
for (dbp=parent->entries; dbp != NULL; dbp = dbp->next)
sortEntriesRecursively(dbp->entries,cmp_proc);
DEBUG1(" done sorting entries recursively for 0x%x\n",parent);
}
/*
* Sorts entries of parent using a selection sort and the given cmp_proc.
*/
void
sortEntries(parent,cmp_proc)
DbEntry *parent;
int (*cmp_proc)();
{
DbEntry *p,*nextp,*lowest,*q,*pnext,*pprev;
DEBUG1(" sorting entries for 0x%x\n",parent);
for (p = parent->entries; p != NULL; p = nextp) {
nextp = p->next;
lowest = p;
for (q = p->next; q != NULL; q = q->next)
if ((*cmp_proc)(q,lowest) < 0)
lowest = q;
if (p != lowest) {
/* swap the two links */
pnext = p->next;
pprev = p->prev;
if (lowest->next != NULL)
lowest->next->prev = p;
p->next = lowest->next;
if (nextp == lowest) {
p->prev = lowest;
} else {
lowest->prev->next = p;
p->prev = lowest->prev;
}
if (nextp == lowest) {
lowest->next = p;
} else {
pnext->prev = lowest;
lowest->next = pnext;
}
if (pprev != NULL)
pprev->next = lowest;
lowest->prev = pprev;
/* keep the head of the list in the right place */
if (parent->entries == p)
parent->entries = lowest;
}
}
DEBUG1(" done sorting entries for 0x%x\n",parent);
}
/*
* cmpEntryNames(p,q) : Compare entries by name. Returns < 0 if p belongs
* before q, > 0 if q belongs before p, and == 0 if names are identical.
*/
int
cmpEntryNames(p,q)
DbEntry *p,*q;
{
return(strcmp(p->name,q->name));
}
/*
* cmpEntryDates(p,q) : Compare entries by date. If the dates are the same
* or both entries don't have a date, then compare by name.
*
* To make this useful, I've made it sort hosts and locations by the
* newest thing in them. To make it faster, it caches the computed date
* in the otherwise unused date field.
*/
int
cmpEntryDates(p,q)
DbEntry *p,*q;
{
int result;
if (!*(p->gt_date))
p->gt_date = entryDate(p);
if (!*(q->gt_date))
q->gt_date = entryDate(q);
if ((result=strcmp(q->gt_date,p->gt_date)) != 0) /* note order! */
return(result);
else
return(cmpEntryNames(p,q));
}
static char *
entryDate(dbp)
DbEntry *dbp;
{
if (dbp->type == DB_HOST)
return(hostDate(dbp));
else if (dbp->type == DB_LOCATION)
return(locationDate(dbp));
else
return(dbp->gt_date);
}
/*
* Returns the date of the newest (biggest date) location in the host.
*/
static char *
hostDate(dbp)
DbEntry *dbp;
{
DbEntry *loc;
char *date = "";
char *locdate;
for (loc=dbp->entries; loc != NULL; loc=loc->next) {
locdate = locationDate(loc);
if (!*date || strcmp(date,locdate) < 0)
date = locdate;
}
return(date);
}
/*
* Returns the date of the newest (biggest date) entry in the location.
*/
static char *
locationDate(dbp)
DbEntry *dbp;
{
DbEntry *file;
char *date = "";
for (file=dbp->entries; file != NULL; file=file->next) {
if (!*date || strcmp(date,file->gt_date) < 0)
date = file->gt_date;
}
return(date);
}
/*
* cmpEntryWeights(p,q) : Compare entries by user-defined "weights".
*/
int
cmpEntryWeights(p,q)
DbEntry *p,*q;
{
int result;
if ((result=hostWeight(p->name)-hostWeight(q->name)) != 0)
return(result);
else
return(cmpEntryNames(p,q));
}